Programlama dili kitapları, bu iki şeyin ne olduğunu açıklamadan değer türlerinin yığın üzerinde oluşturulduğunu ve yığın üzerinde referans türlerinin oluşturulduğunu açıklar. Bunun net bir açıklamasını okumadım. Yığının ne olduğunu anlıyorum. Fakat, Nerede ve nedir (fiziksel olarak gerçek bir bilgisayarın belleğinde)? İşletim sistemi veya dil çalışma zamanı tarafından ne ölçüde kontrol ediliyorlar? Kapsamları nedir? Her birinin boyutunu ne belirler? Birini daha hızlı yapan nedir?
2020-12-07 21:45:14
Yığın, bir yürütme iş parçacığı için boş alan olarak ayrılan bellektir. Bir işlev çağrıldığında, yığının en üstünde yerel değişkenler ve bazı defter tutma verileri için bir blok ayrılır. Bu fonksiyon geri döndüğünde, blok kullanılmaz hale gelir ve bir sonraki fonksiyon çağrıldığında kullanılabilir. Yığın her zaman bir LIFO (son giren ilk çıkar) sırasına göre ayrılır; en son ayrılan blok her zaman serbest bırakılacak bir sonraki bloktur. Bu, yığını takip etmeyi gerçekten kolaylaştırır; yığından bir bloğu çıkarmak, bir işaretçiyi ayarlamaktan başka bir şey değildir. Yığın, dinamik ayırma için bir kenara ayrılmış bellektir. Yığının aksine, öbekten blokların tahsisi ve serbest bırakılması için zorunlu bir model yoktur; İstediğiniz zaman bir blok tahsis edebilir ve istediğiniz zaman serbest bırakabilirsiniz. Bu, herhangi bir zamanda yığının hangi bölümlerinin tahsis edildiğini veya ücretsiz olduğunu takip etmeyi çok daha karmaşık hale getirir; Farklı kullanım modelleri için yığın performansını ayarlamak için birçok özel yığın ayırıcı mevcuttur. Her iş parçacığı bir yığın alır, ancak uygulama için tipik olarak yalnızca bir yığın vardır (ancak farklı ayırma türleri için birden çok yığın olması nadir değildir). Sorularınızı doğrudan cevaplamak için: İşletim sistemi veya dil çalışma zamanı tarafından ne ölçüde kontrol ediliyorlar? İşletim sistemi, iş parçacığı oluşturulduğunda yığını her sistem düzeyindeki iş parçacığı için ayırır. Tipik olarak işletim sistemi, uygulama için yığın ayırmak üzere dil çalışma zamanı tarafından çağrılır. Kapsamları nedir? Yığın bir iş parçacığına eklenir, böylece iş parçacığı çıktığında yığın geri alınır. Yığın, tipik olarak uygulama başlangıcında çalışma zamanı tarafından tahsis edilir ve uygulama (teknik olarak işlem) çıktığında geri alınır. Her birinin boyutunu ne belirler? Yığının boyutu, bir iş parçacığı oluşturulduğunda belirlenir. Yığının boyutu uygulama başlangıcında belirlenir, ancak alan gerektiğinde büyüyebilir (ayırıcı işletim sisteminden daha fazla bellek ister). Birini daha hızlı yapan nedir? Yığın daha hızlıdır çünkü erişim modeli, bellek ayırmayı ve ayırmayı önemsiz hale getirir (bir işaretçi / tamsayı basitçe artırılır veya azaltılır), öbek ise bir ayırma veya ayırma işlemiyle ilgili çok daha karmaşık defter tutma içerir. Ayrıca, yığındaki her bir bayt çok sık yeniden kullanılma eğilimindedir, bu da işlemcinin önbelleğine eşleme eğiliminde olduğu anlamına gelir ve bu da onu çok hızlı yapar. Yığın için bir başka performans vuruşu, çoğunlukla küresel bir kaynak olan yığının tipik olarak çok iş parçacıklı güvenli olması gerektiğidir, yani her ayırma ve serbest bırakmanın - tipik olarak - programdaki "tüm" diğer yığın erişimleriyle senkronize edilmesi gerekir. Açık bir gösteri: Resim kaynağı: vikashazrati.wordpress.com | Yığın: Tıpkı yığın gibi bilgisayar RAM'inde saklanır. Yığın üzerinde oluşturulan değişkenler kapsam dışına çıkar ve otomatik olarak serbest bırakılır. Yığın üzerindeki değişkenlere kıyasla ayırmak çok daha hızlı. Gerçek bir yığın veri yapısı ile uygulanır. Parametre geçişi için kullanılan yerel verileri, dönüş adreslerini depolar. Çok fazla yığın kullanıldığında yığın taşması olabilir (çoğunlukla sonsuz veya çok derin özyinelemeden, çok büyük tahsislerden). Yığın üzerinde oluşturulan veriler işaretçiler olmadan kullanılabilir. Derleme zamanından önce tam olarak ne kadar veri ayırmanız gerektiğini biliyorsanız ve çok büyük değilse yığını kullanırsınız. Genellikle programınız başladığında önceden belirlenmiş bir maksimum boyuta sahiptir. Yığın: Tıpkı yığın gibi bilgisayar RAM'inde saklanır. C ++ 'da, yığın üzerindeki değişkenler elle yok edilmeli ve asla kapsam dışına çıkmamalıdır. Veriler silme, silme [] veya ücretsiz olarak serbest bırakılır. Yığın üzerindeki değişkenlere kıyasla ayırmak daha yavaştır. Program tarafından kullanılmak üzere bir veri bloğu tahsis etmek için isteğe bağlı olarak kullanılır. Çok sayıda ayırma ve serbest bırakma olduğunda parçalanma olabilir. C ++ veya C'de, yığın üzerinde oluşturulan veriler işaretçilerle gösterilecek ve sırasıyla new veya malloc ile tahsis edilecektir. Çok büyük bir arabellek ayrılması istenirse, ayırma hataları olabilir. Çalışma zamanında tam olarak ne kadar veriye ihtiyacınız olacağını bilmiyorsanız veya çok fazla veri ayırmanız gerekiyorsa, yığını kullanırsınız. Hafıza sızıntılarından sorumlu. Misal: int foo () { char * pBuffer; // <- henüz ayrılmamış (burada yığın üzerinde ayrılmış olan işaretçinin kendisi hariç). bool b = doğru; // Yığın üzerinde ayrılmıştır. eğer (b) { // Yığın üzerinde 500 bayt oluştur karakter tamponu [500]; // Yığın üzerinde 500 bayt oluştur pBuffer = yeni karakter [500]; } // <- arabellek burada ayrılır, pBuffer değil } // <--- oops bir bellek sızıntısı var, delete [] pBuffer'ı çağırmalıydım; | En önemli nokta, yığın ve yığının, belleğin tahsis edilebileceği yollar için genel terimler olmasıdır. Birçok farklı şekilde uygulanabilirler ve terimler temel kavramlar için geçerlidir. Bir öğe yığınında, öğeler oraya yerleştirildikleri sırayla üst üste oturur ve yalnızca en üstteki öğeyi kaldırabilirsiniz.(her şeyi devirmeden). Bir yığının basitliği, ayrılan belleğin her bölümünün kaydını içeren bir tablo tutmanıza gerek olmamasıdır; İhtiyacınız olan tek durum bilgisi, yığının sonuna giden tek bir işaretçidir. Tahsis etmek ve ayırmak için, sadece o tek işaretçiyi artırır ve azaltırsınız. Not: Bir yığın bazen belleğin bir bölümünün tepesinden başlamak ve yukarı doğru büyümek yerine aşağı doğru genişletmek için uygulanabilir. Bir yığın içinde, öğelerin yerleştirilme şekline ilişkin belirli bir sıra yoktur. Net bir 'üst' öğe olmadığından, herhangi bir sırayla ürünlere ulaşabilir ve kaldırabilirsiniz. Yığın tahsisi, hangi belleğin ayrıldığına ve neyin ayrılmadığına dair tam bir kayıt tutmayı ve parçalanmayı azaltmak için bazı ek bakım işlemlerini, istenen boyuta uyacak kadar büyük bitişik bellek bölümlerini bulmayı, vb. Gerektirir. Bellek, boş alan bırakılarak herhangi bir zamanda serbest bırakılabilir. Bazen bir bellek ayırıcı, ayrılan belleği hareket ettirerek belleği birleştirme veya çöp toplama gibi bakım görevlerini gerçekleştirir - bellek artık kapsamda olmadığında çalışma zamanında tanımlama ve onu serbest bırakma. Bu görüntüler, belleği bir yığın ve bir yığın içinde ayırmanın ve serbest bırakmanın iki yolunu açıklamak için oldukça iyi bir iş çıkarır. Yum! İşletim sistemi veya dil çalışma zamanı tarafından ne ölçüde kontrol ediliyorlar? Belirtildiği gibi, yığın ve yığın genel terimlerdir ve birçok şekilde uygulanabilir. Bilgisayar programlarında, tipik olarak, çağrıldığı işleve yönelik bir işaretçi ve herhangi bir yerel değişken gibi geçerli işlevle ilgili bilgileri depolayan, çağrı yığını adı verilen bir yığın vardır. İşlevler diğer işlevleri çağırıp sonra geri döndüğünden, yığın büyür ve işlevlerden gelen bilgileri çağrı yığınının aşağısında tutmak için küçülür. Bir programın üzerinde çalışma zamanı kontrolü yoktur; programlama dili, işletim sistemi ve hatta sistem mimarisi tarafından belirlenir. Yığın, dinamik ve rasgele tahsis edilen herhangi bir bellek için kullanılan genel bir terimdir; yani sıra dışı. Bellek tipik olarak işletim sistemi tarafından tahsis edilir ve uygulama bu ayırmayı yapmak için API işlevlerini çağırır. Genellikle kullanılan programlama dilinin veya ortamın çalışma zamanı kodu tarafından işlenen, dinamik olarak tahsis edilmiş belleğin yönetilmesinde gerekli olan oldukça fazla ek yük vardır. Kapsamları nedir? Çağrı yığını o kadar düşük seviyeli bir kavramdır ki, programlama anlamında 'kapsam' ile ilgili değildir. Bazı kodu parçalara ayırırsanız, yığının bölümlerine göre işaretçi stili referansları görürsünüz, ancak daha yüksek seviyeli bir dil söz konusu olduğunda, dil kendi kapsam kurallarını dayatır. Bununla birlikte, bir yığının önemli bir yönü, bir işlev geri döndüğünde, bu işlev için yerel olan her şeyin yığından hemen kurtarılmasıdır. Bu, programlama dillerinizin nasıl çalıştığına bağlı olarak çalışmasını beklediğiniz şekilde çalışır. Bir yığın halinde tanımlamak da zordur. Kapsam, işletim sistemi tarafından sunulan şeydir, ancak programlama diliniz muhtemelen uygulamanızda bir "kapsam" ın ne olduğuna ilişkin kurallarını ekler. İşlemci mimarisi ve işletim sistemi, işlemcinin fiziksel adreslere çevirdiği ve sayfa hataları vb. Olan sanal adreslemeyi kullanır. Hangi sayfaların hangi uygulamalara ait olduğunu izlerler. Bununla birlikte, bunun için asla gerçekten endişelenmenize gerek yok, çünkü programlama dilinizin belleği ayırmak ve boşaltmak için kullandığı yöntemi kullanırsınız ve hataları kontrol edersiniz (ayırma / boşaltma herhangi bir nedenle başarısız olursa). Her birinin boyutunu ne belirler? Yine, dile, derleyiciye, işletim sistemine ve mimariye bağlıdır. Yığın genellikle önceden tahsis edilir, çünkü tanım gereği bitişik bellek olması gerekir. Dil derleyicisi veya işletim sistemi boyutunu belirler. Yığın üzerinde büyük miktarda veri depolamıyorsunuz, bu nedenle istenmeyen sonsuz özyineleme (dolayısıyla "yığın taşması") veya diğer olağandışı programlama kararları dışında hiçbir zaman tam olarak kullanılmaması için yeterince büyük olacaktır. Yığın, dinamik olarak tahsis edilebilen herhangi bir şey için genel bir terimdir. Hangi yönden baktığınıza bağlı olarak, sürekli boyut değiştiriyor. Modern işlemcilerde ve işletim sistemlerinde tam olarak çalışma şekli zaten çok soyuttur, bu nedenle normalde nasıl çalıştığı konusunda çok endişelenmenize gerek yoktur, ancak (size izin verdiği dillerde) Henüz ayırmadınız veya serbest bıraktığınız hafıza. Birini daha hızlı yapan nedir? Yığın daha hızlıdır çünkü tüm boş bellek her zaman bitişiktir. Boş belleğin tüm bölümlerinin listesinin tutulması gerekmez, yığının geçerli üst kısmına tek bir işaretçi yeterlidir. Derleyiciler genellikle bu işaretçiyi bu amaç için özel ve hızlı bir kayıt defterinde saklar. Dahası, bir yığın üzerindeki sonraki işlemler genellikle belleğin çok yakın alanlarında yoğunlaşır, bu da çok düşük bir seviyede işlemcinin kalıp üzerinde optimizasyonu için iyidirönbellekler. | (Bu yanıtı, aşağı yukarı bunun bir kopyası olan başka bir sorudan aldım.) Sorunuzun cevabı uygulamaya özeldir ve derleyiciler ile işlemci mimarileri arasında farklılık gösterebilir. Bununla birlikte, işte basitleştirilmiş bir açıklama. Hem yığın hem de yığın, temeldeki işletim sisteminden ayrılmış bellek alanlarıdır (genellikle isteğe bağlı olarak fiziksel belleğe eşlenen sanal bellek). Çok iş parçacıklı bir ortamda, her iş parçacığı kendi tamamen bağımsız yığınına sahip olacak, ancak yığını paylaşacaklar. Eşzamanlı erişim yığın üzerinde denetlenmelidir ve yığın üzerinde mümkün değildir. Yığın Yığın, kullanılmış ve serbest blokların bağlantılı bir listesini içerir. Yığın üzerindeki yeni tahsisler (yeni veya malloc tarafından), ücretsiz blokların birinden uygun bir blok oluşturarak karşılanır. Bu, yığın üzerindeki blok listesinin güncellenmesini gerektirir. Yığın üzerindeki bloklarla ilgili bu meta bilgi, genellikle her bloğun hemen önündeki küçük bir alanda yığında depolanır. Yığın büyüdükçe yeni bloklar genellikle daha düşük adreslerden daha yüksek adreslere tahsis edilir. Böylece, yığını, bellek ayrıldığında boyutu büyüyen bir bellek blokları yığını olarak düşünebilirsiniz. Yığın bir ayırma için çok küçükse, boyut genellikle temeldeki işletim sisteminden daha fazla bellek alınarak artırılabilir. Birçok küçük bloğun tahsis edilmesi ve ayrılması, yığını, kullanılan bloklar arasına serpiştirilmiş çok sayıda küçük serbest bloğun bulunduğu bir durumda bırakabilir. Büyük bir bloğun tahsis edilmesi talebi başarısız olabilir, çünkü serbest blokların hiçbiri, serbest blokların birleşik boyutu yeterince büyük olsa bile, tahsis talebini karşılayacak kadar büyük değildir. Buna yığın parçalama denir. Serbest bir bloğa bitişik olan kullanılmış bir bloğun ayrılması durumunda, yeni serbest blok, yığının parçalanmasını etkili bir şekilde azaltan daha büyük bir serbest blok oluşturmak için bitişik serbest blok ile birleştirilebilir. Yığın Yığın, genellikle CPU üzerinde yığın işaretçisi olarak adlandırılan özel bir kayıtla yakın bir şekilde çalışır. Başlangıçta yığın işaretçisi yığının en üstüne (yığındaki en yüksek adres) işaret eder. CPU, değerleri yığına göndermek ve yığından geri çıkarmak için özel talimatlara sahiptir. Her itme, değeri yığın işaretçisinin geçerli konumunda depolar ve yığın işaretçisini azaltır. Bir pop, yığın işaretçisinin gösterdiği değeri alır ve ardından yığın işaretçisini artırır (yığına bir değer eklemenin yığın işaretçisini azaltması ve bir değeri kaldırmanın onu artırması gerçeğiyle karıştırılmayın. alt). Saklanan ve alınan değerler, CPU kayıtlarının değerleridir. Bir işlev çağrıldığında CPU, geçerli talimat işaretçisini, yani yığın üzerinde çalışan kodun adresini iten özel komutlar kullanır. Daha sonra CPU, ayarlayarak işleve atlar. çağrılan işlevin adresine yönerge işaretçisi. Daha sonra, işlev geri döndüğünde, eski komut işaretçisi yığından çıkar ve işlev çağrısından hemen sonra kodda yürütme devam eder. Bir fonksiyon girildiğinde, yerel (otomatik) değişkenler için yığın üzerinde daha fazla alan ayırmak için yığın işaretçisi azaltılır. Fonksiyonun bir yerel 32 bit değişkeni varsa, yığın üzerinde dört bayt bir kenara bırakılır. İşlev geri döndüğünde, yığın işaretçisi ayrılmış alanı boşaltmak için geri taşınır. Bir fonksiyonun parametreleri varsa, bunlar fonksiyon çağrılmadan önce yığına itilir. Fonksiyondaki kod daha sonra bu değerleri bulmak için mevcut yığın işaretçisinden yığında yukarı doğru gezinebilir. Yuvalama işlevi çağrıları bir cazibe gibi çalışır. Her yeni çağrı, fonksiyon parametreleri, dönüş adresi ve yerel değişkenler için alan tahsis edecektir ve bu aktivasyon kayıtları iç içe çağrılar için yığınlanabilir ve fonksiyonlar geri döndüğünde doğru şekilde çözülür. Yığın sınırlı bir bellek bloğu olduğundan, çok fazla iç içe geçmiş işlevi çağırarak ve / veya yerel değişkenler için çok fazla alan ayırarak bir yığın taşmasına neden olabilirsiniz. Genellikle yığın için kullanılan bellek alanı, yığının en altına (en düşük adres) yazmanın CPU'da bir tuzağı veya istisnayı tetikleyeceği şekilde ayarlanır. Bu istisnai durum daha sonra çalışma zamanı tarafından yakalanabilir ve bir tür yığın taşması istisnasına dönüştürülebilir. Yığın yerine yığın üzerinde bir işlev tahsis edilebilir mi? Hayır, işlevler için etkinleştirme kayıtları (yani yerel veya otomatik değişkenler), yalnızca bu değişkenleri depolamak için değil, aynı zamanda iç içe geçmiş işlev çağrılarını takip etmek için kullanılan yığın üzerine tahsis edilir. Yığının nasıl yönetildiği gerçekten çalışma zamanı ortamına bağlıdır. C malloc kullanır ve C ++ yeni kullanır, ancak diğer birçok dilde çöp toplama vardır. Ancak yığın, işlemci mimarisine yakından bağlı daha düşük seviyeli bir özelliktir. Yeterli alan olmadığında yığını büyütmek o zamandan beri çok zor değilyığını işleyen kütüphane çağrısında uygulanabilir. Bununla birlikte, yığın taşması yalnızca çok geç olduğunda keşfedildiği için yığını büyütmek genellikle imkansızdır; ve yürütme sürecini kapatmak tek geçerli seçenektir. | Aşağıdaki C # kodunda public void Method1 () { int i = 4; int y = 2; sınıf1 cls1 = yeni sınıf1 (); } İşte bellek nasıl yönetiliyor Yalnızca işlev çağrısı yığına girdiği sürece sürmesi gereken Yerel Değişkenler. Yığın, yaşam sürelerini önceden bilmediğimiz, ancak bir süre sürmesini beklediğimiz değişkenler için kullanılır. Çoğu dilde, bir değişkeni yığın üzerinde depolamak istiyorsak, derleme zamanında bir değişkenin ne kadar büyük olduğunu bilmemiz çok önemlidir. Nesneler (biz onları güncelledikçe boyutları değişir) yığına gider çünkü yaratma sırasında ne kadar dayanacaklarını bilmiyoruz. Pek çok dilde yığın, artık referansı olmayan nesneleri (cls1 nesnesi gibi) bulmak için çöp olarak toplanır. Java'da çoğu nesne doğrudan yığına gider. C / C ++ gibi dillerde, işaretçilerle uğraşmadığınız zamanlarda yapılar ve sınıflar genellikle yığında kalabilir. Daha fazla bilgi burada bulunabilir: Yığın ve yığın bellek ayırma arasındaki fark «timmurphy.org ve burada: Yığın ve Yığın Üzerinde Nesne Oluşturma Bu makale yukarıdaki resmin kaynağıdır: Altı önemli .NET kavramı: Yığın, yığın, değer türleri, başvuru türleri, kutulama ve kutudan çıkarma - CodeProject ancak bazı yanlışlıklar içerebileceğini unutmayın. | Yığın Bir işlevi çağırdığınızda, o işleve yönelik argümanlar ve diğer bazı ek yükler yığına konur. Bazı bilgiler (dönüşte nereye gideceğiniz gibi) da burada saklanır. Fonksiyonunuzun içinde bir değişken tanımladığınızda, bu değişken de yığın üzerinde tahsis edilir. Yığının serbest bırakılması oldukça basittir çünkü her zaman ayırdığınız sıranın tersi sırayla yeniden ayırırsınız. İşlevlere girerken yığın öğeleri eklenir, bunlardan çıktığınızda karşılık gelen veriler kaldırılır. Bu, çok sayıda başka işlevi çağıran (veya özyinelemeli bir çözüm oluşturmayan) çok sayıda işlev çağırmadığınız sürece yığının küçük bir bölgesinde kalma eğiliminde olduğunuz anlamına gelir. Yığın Yığın, anında oluşturduğunuz verileri koyduğunuz yere ilişkin genel bir addır. Programınızın kaç uzay gemisi yaratacağını bilmiyorsanız, her bir uzay gemisini oluşturmak için yeni (veya malloc veya eşdeğeri) operatörünü kullanmanız muhtemeldir. Bu tahsis bir süre daha takılıp kalmayacak, bu yüzden büyük olasılıkla şeyleri yarattığımızdan farklı bir düzende serbest bırakacağız. Bu nedenle, yığın çok daha karmaşıktır, çünkü sonunda, bellek parçalanmış olan yığınlarla iç içe geçmiş kullanılmayan bellek bölgeleri ortaya çıkar. İhtiyacınız olan boyutta boş hafıza bulmak zor bir sorundur. Bu nedenle yığıntan kaçınılmalıdır (yine de sıklıkla kullanılmaktadır). Uygulama Hem yığının hem de yığının uygulanması genellikle çalışma zamanına / işletim sistemine bağlıdır. Çoğunlukla, performans açısından kritik önem taşıyan oyunlar ve diğer uygulamalar, yığıntan büyük bir bellek parçası alan ve ardından bellek için işletim sistemine güvenmekten kaçınmak için bunu dahili olarak dağıtan kendi bellek çözümlerini oluşturur. Bu, yalnızca bellek kullanımınız normdan oldukça farklıysa pratiktir - yani, büyük bir işlemde bir seviye yüklediğiniz ve her şeyi başka bir büyük operasyonda uzaklaştırabileceğiniz oyunlar için. Bellekte fiziksel konum Bu, programınızın fiziksel verilerin başka bir yerde (hatta sabit diskte!) Olduğu belirli bir adrese erişiminiz olduğunu düşünmesine neden olan Sanal Bellek adlı bir teknoloji nedeniyle düşündüğünüzden daha az ilgilidir. Yığın için aldığınız adresler, çağrı ağacınız derinleştikçe artmaktadır. Yığın için adresler tahmin edilemez (yani uygulamaya özel) ve açıkçası önemli değil. | Açıklığa kavuşturmak için, bu cevapta yanlış bilgi var (thomas yorumlardan sonra cevabını düzeltti, harika :)). Diğer cevaplar sadece statik ayırmanın ne anlama geldiğini açıklamamaktan kaçınır. Bu nedenle, üç ana ayırma biçimini ve bunların genellikle aşağıdaki yığın, yığın ve veri segmentiyle nasıl ilişkili olduğunu açıklayacağım. Ayrıca insanların anlamasına yardımcı olmak için hem C / C ++ hem de Python'da bazı örnekler göstereceğim. "Statik" (statik olarak ayrılmış AKA) değişkenler yığın üzerinde tahsis edilmez. Öyle varsaymayın - çoğu insan sadece "statik" sesi "yığın" gibi ses çıkardığı için bunu yapar. Aslında ne yığın ne de yığın içinde varlar. Veri segmenti denen şeyin bir parçasıdır. Ancak, genellikle "yığın" ve "yığın" yerine "kapsam" ve "ömür" olarak düşünmek daha iyidir. Kapsam, kodun hangi bölümlerinin bir değişkene erişebileceğini ifade eder. Kapsam çok daha karmaşık hale gelebilmesine rağmen, genel olarak yerel kapsam (yalnızca mevcut işlev tarafından erişilebilir) yerine küresel kapsam (her yerden erişilebilir) düşünülür. Yaşam süresi, programın yürütülmesi sırasında bir değişkenin tahsis edildiği ve serbest bırakıldığı zamanı ifade eder. Genellikle statik ayırmayı düşünürüz (değişkenprogramın tüm süresi boyunca devam eder, bu da aynı bilgiyi birkaç işlev çağrısında saklamak için yararlı hale getirir) ve otomatik ayırma (değişken yalnızca bir işleve yapılan tek bir çağrı sırasında kalır, bu da onu yalnızca sizin dinamik ayırmaya (statik veya otomatik gibi derleme zamanı yerine çalışma zamanında tanımlanan değişkenler) karşı işiniz bittiğinde atılabilir ve atılabilir. Çoğu derleyici ve yorumlayıcı bu davranışı yığınlar, yığınlar vb. Kullanım açısından benzer şekilde uygulamasına rağmen, bir derleyici davranış doğru olduğu sürece isterse bazen bu kuralları bozabilir. Örneğin, optimizasyon nedeniyle yerel bir değişken yalnızca bir kayıtta bulunabilir veya yığın içinde çoğu yerel değişken bulunsa bile tamamen kaldırılabilir. Birkaç yorumda belirtildiği gibi, bir yığın veya yığın bile kullanmayan, bunun yerine başka depolama mekanizmaları (yığınlar ve yığınlar bunun için harika olduğu için nadiren yapılır) uygulamakta özgürsünüz. Tüm bunları açıklamak için bazı basit açıklamalı C kodu sağlayacağım. Öğrenmenin en iyi yolu, bir programı bir hata ayıklayıcı altında çalıştırmak ve davranışı izlemektir. Python okumayı tercih ederseniz cevabın sonuna atlayın :) // Program / DLL ilk yüklendiğinde veri segmentinde statik olarak ayrılır // Program / DLL çıktığında serbest bırakıldı // kapsam - kodun herhangi bir yerinden erişilebilir int someGlobalVariable; // Program ilk yüklendiğinde veri segmentinde statik olarak tahsis edilir // Program / DLL çıktığında serbest bırakıldı // kapsam - bu özel kod dosyasındaki herhangi bir yerden erişilebilir statik int bazıStaticVariable; // MyFunction her çağrıldığında yığın üzerinde "birArgument" tahsis edilir // MyFunction döndüğünde "birArgümanın" serbest bırakılması // kapsam - sadece MyFunction () içinden erişilebilir void MyFunction (int someArgument) { // Program ilk yüklendiğinde veri segmentinde statik olarak tahsis edilir // Program / DLL çıktığında serbest bırakıldı // kapsam - sadece MyFunction () içinden erişilebilir statik int someLocalStaticVariable; // MyFunction her çağrıldığında yığın üzerinde ayrılır // MyFunction döndüğünde serbest bırakıldı // kapsam - sadece MyFunction () içinden erişilebilir int someLocalVariable; // MyFunction her çağrıldığında yığın üzerinde bir * işaretçi * tahsis edilir // MyFunction döndüğünde bu işaretçi serbest bırakılır // kapsam - işaretçiye yalnızca MyFunction () içinden erişilebilir int * someDynamicVariable; // Bu satır, yığın içinde bir tamsayı için yer ayrılmasına neden olur // bu satır çalıştırıldığında. Bunun başlangıcında olmadığını unutmayın // Otomatik değişkenler gibi MyFunction () çağrısı // kapsam - bu alana yalnızca MyFunction () içindeki kod erişebilir // * bu belirli değişken aracılığıyla *. // Ancak, adresi başka bir yere iletirseniz, bu kod // ona da erişebilir someDynamicVariable = yeni int; // Bu satır, öbekteki tamsayı için alanı serbest bırakır. // Biz yazmasaydık bellek "sızardı". // Yığın ve yığın arasındaki temel farkı not edin // yığın yönetilmelidir. Yığın bizim için yönetiliyor. someDynamicVariable'ı sil; // Diğer durumlarda, bu yığın alanını serbest bırakmak yerine // adresi daha sonra kullanmak için daha kalıcı bir yerde saklayabilir. // Bazı diller sizin için serbest bırakmayı bile halleder ... ama // her zaman çalışma zamanında bir mekanizma tarafından halledilmesi gerekir. // İşlev döndüğünde, someArgument, someLocalVariable // ve someDynamicVariable işaretçisi serbest bırakılır. // someDynamicVariable'ın işaret ettiği boşluk zaten // geri dönmeden önce serbest bırakıldı. dönüş; } // someGlobalVariable, someStaticVariable ve // someLocalStaticVariable var olmaya devam ediyor ve değil // program çıkana kadar serbest bırakıldı. Yaşam süresi ile kapsam arasında ayrım yapmanın neden önemli olduğuna dair özellikle çarpıcı bir örnek, bir değişkenin yerel kapsama sahip olmasına karşın statik yaşam süresine sahip olmasıdır - örneğin, yukarıdaki kod örneğinde "someLocalStaticVariable". Bu tür değişkenler, yaygın ancak gayri resmi adlandırma alışkanlıklarımızı çok kafa karıştırıcı hale getirebilir. Örneğin, "yerel" dediğimizde, genellikle "yerel kapsamlı otomatik olarak ayrılmış değişken" demek istiyoruz ve global dediğimizde genellikle "küresel kapsamlı statik olarak ayrılmış değişken" demek istiyoruz. Maalesef "dosya kapsamlı statik olarak ayrılmış değişkenler" gibi şeyler söz konusu olduğunda birçok kişi sadece ... "ha ???" der. C / C ++ 'daki bazı sözdizimi seçimleri bu sorunu daha da şiddetlendirir - örneğin birçok kişi aşağıda gösterilen sözdizimi nedeniyle global değişkenlerin "statik" olmadığını düşünür. int var1; // Global kapsam ve statik ayırmaya sahiptir statik int var2; // Dosya kapsamı ve statik ayırma var int main () {dönüş 0;} Yukarıdaki bildirime "statik" anahtar sözcüğünü koymanın var2'nin genel kapsama sahip olmasını engellediğini unutmayın. Bununla birlikte, global var1 statik ayırmaya sahiptir. Bu değilsezgisel! Bu nedenle, kapsamı açıklarken asla "statik" kelimesini kullanmamaya çalışıyorum ve bunun yerine "dosya" veya "dosya sınırlı" kapsam gibi bir şey söylüyorum. Ancak birçok kişi, yalnızca bir kod dosyasından erişilebilen bir değişkeni tanımlamak için "statik" veya "statik kapsam" ifadesini kullanır. Yaşam süresi bağlamında, "statik" her zaman değişkenin program başlangıcında tahsis edildiği ve program çıkıldığında serbest bırakıldığı anlamına gelir. Bazı insanlar bu kavramların C / C ++ 'ya özgü olduğunu düşünür. Onlar değil. Örneğin, aşağıdaki Python örneği, üç tahsis türünü de gösterir (burada girmeyeceğim yorumlanmış dillerde olası bazı ince farklılıklar vardır). tarih saatinden içe aktarma tarih saatinden sınıf Hayvan: _FavoriteFood = 'Tanımsız' # _FavoriteFood statik olarak tahsis edilmiştir def PetAnimal (kendi): curTime = datetime.time (datetime.now ()) # curTime otomatik olarak ayrılır print ("Beni sevdiğin için teşekkür ederim. Ama bu" + str (curTime) + ", beni beslemelisin. En sevdiğim yemek" + self._FavoriteFood) sınıf Kedi (Hayvan): _FavoriteFood = 'tuna' # Geçersiz kıldığımıza dikkat edin, Cat sınıfının Animal sınıfından farklı olarak statik olarak ayrılmış _FavoriteFood değişkeni vardır. sınıf Köpek (Hayvan): _FavoriteFood = 'steak' # Aynı şekilde, Dog sınıfı da kendi statik değişkenini alır. Unutulmaması gereken önemli - bu statik değişken, Dog'un tüm örnekleri arasında paylaşılır, bu nedenle dinamik değildir! __name__ == "__main__" ise: bıyık = Kedi () # Dinamik olarak ayrılmış fido = Köpek () # Dinamik olarak tahsis edilmiş rinTinTin = Köpek () # Dinamik olarak tahsis edilmiş whiskers.PetAnimal () fido.PetAnimal () rinTinTin.PetAnimal () Dog._FavoriteFood = 'süt kemiği' whiskers.PetAnimal () fido.PetAnimal () rinTinTin.PetAnimal () # Çıktı: # Beni okşadığınız için teşekkür ederim. Ama saat 13: 05: 02.255000, beni beslemelisin. En sevdiğim yemek ton balığı # Beni okşadığınız için teşekkür ederim. Ama saat 13: 05: 02.255000, beni beslemelisin. En sevdiğim yemek biftek # Beni okşadığınız için teşekkür ederim. Ama saat 13: 05: 02.255000, beni beslemelisin. En sevdiğim yemek biftek # Beni okşadığınız için teşekkür ederim. Ama saat 13: 05: 02.255000, beni beslemelisin. En sevdiğim yemek ton balığı # Beni okşadığınız için teşekkür ederim. Ama saat 13: 05: 02.255000, beni beslemelisin. En sevdiğim yemek süt kemiği # Beni okşadığınız için teşekkür ederim. Ama saat 13: 05: 02.256000, beni beslemelisin. En sevdiğim yemek süt kemiği | Başkaları geniş vuruşlara oldukça iyi cevap verdi, bu yüzden birkaç ayrıntı vereceğim. Yığın ve yığının tekil olması gerekmez. Birden fazla yığına sahip olduğunuz yaygın bir durum, bir işlemde birden fazla iş parçacığınızın olmasıdır. Bu durumda, her iş parçacığının kendi yığını vardır. Birden fazla öbeğiniz de olabilir, örneğin bazı DLL yapılandırmaları farklı yığınlardan farklı DLL'lerin ayrılmasına neden olabilir, bu nedenle farklı bir kitaplık tarafından ayrılan belleği serbest bırakmak genellikle kötü bir fikirdir. C'de, yığın üzerinde tahsis eden ayırmanın aksine yığın üzerinde tahsis eden alloca kullanımıyla değişken uzunluk tahsisinden yararlanabilirsiniz. Bu bellek, dönüş ifadenizden sağ çıkmaz, ancak bir çalışma tamponu için kullanışlıdır. Windows'ta çok kullanmadığınız büyük bir geçici arabellek oluşturmak ücretsiz değildir. Bunun nedeni, derleyicinin yığının var olduğundan emin olmak için işlevinize her girildiğinde çağrılan bir yığın yoklama döngüsü oluşturmasıdır (çünkü Windows yığının ne zaman büyümesi gerektiğini algılamak için yığının sonunda tek bir koruma sayfası kullanır. Belleğe yığının sonunda birden fazla sayfadan erişirseniz çökersiniz). Misal: void myfunction () { char büyük [10000000]; // Zamanın% 99'unun yalnızca ilk 1K'sı için kullanılan bir şey yapın. } | Diğerleri sorunuzu doğrudan cevapladı, ancak yığını ve yığını anlamaya çalışırken, geleneksel bir UNIX işleminin bellek düzenini (iş parçacıkları ve mmap () tabanlı ayırıcılar olmadan) dikkate almanın yararlı olacağını düşünüyorum. Bellek Yönetimi Sözlüğü web sayfasında bu bellek düzeninin bir diyagramı vardır. Yığın ve yığın geleneksel olarak işlemin sanal adres alanının zıt uçlarında bulunur. Çekirdek tarafından belirlenen bir boyuta kadar (setrlimit (RLIMIT_STACK, ...) ile ayarlanabilir) erişildiğinde yığın otomatik olarak büyür. Bellek ayırıcı brk () veya sbrk () sistem çağrısını çağırdığında yığın büyür ve işlemin sanal adres alanına daha fazla fiziksel bellek sayfası eşler. Bazı gömülü sistemler gibi sanal belleği olmayan sistemlerde, yığın ve yığının boyut olarak sabitlenmesi dışında, genellikle aynı temel düzen geçerlidir. Bununla birlikte, diğer gömülü sistemlerde (Microchip PIC mikro denetleyicilere dayalı olanlar gibi), program yığını, veri hareketi talimatlarıyla adreslenemeyen ayrı bir bellek bloğudur ve yalnızca program akış talimatları (çağrı, dönüş vb.). Intel Itanium işlemcileri gibi diğer mimarilerin birden çok yığını vardır. Bu anlamda, yığın, CPU mimarisinin bir öğesidir. | Yığın bir porsiyon'pop' (yığından bir değeri kaldırma ve döndürme) ve 'itme' (yığına bir değer gönderme) gibi birkaç anahtar montaj dili talimatıyla değiştirilebilen bellek, aynı zamanda çağrı (bir alt rutin çağırın - Yığına dönmek için adresi iter) ve geri döner (bir alt yordamdan geri dönün - bu, adresi yığından çıkarır ve ona atlar). Gerektiğinde ayarlanabilen, yığın işaretçisi kaydının altındaki bellek bölgesidir. Yığın ayrıca argümanları alt rutinlere aktarmak ve ayrıca alt rutinleri çağırmadan önce kayıtlardaki değerleri korumak için kullanılır. Yığın, tipik olarak malloc gibi bir sistem çağrısı aracılığıyla işletim sistemi tarafından bir uygulamaya verilen belleğin bir kısmıdır. Modern işletim sistemlerinde bu bellek, yalnızca arama işleminin erişebildiği bir dizi sayfadır. Yığının boyutu çalışma zamanında belirlenir ve genellikle program başlatıldıktan sonra büyümez. Bir C programında, yığının, her işlevde bildirilen her değişkeni tutacak kadar büyük olması gerekir. Yığın, ihtiyaç duyulduğunda dinamik olarak büyüyecek, ancak işletim sistemi nihayetinde aramayı yapıyor (yığını genellikle malloc tarafından talep edilen değerden daha fazla büyütecek, böylece en azından gelecekteki bazı malloc'ların çekirdeğe geri dönmesi gerekmeyecek. daha fazla bellek edinin. Bu davranış genellikle özelleştirilebilir) Programı başlatmadan önce yığını ayırdığınız için, yığını kullanmadan önce malloc'a asla ihtiyacınız yoktur, bu yüzden bu küçük bir avantajdır. Pratikte, sanal bellek alt sistemlerine sahip modern işletim sistemlerinde neyin hızlı ve neyin yavaş olacağını tahmin etmek çok zordur, çünkü sayfaların nasıl uygulandığı ve nerede depolandıkları bir uygulama ayrıntısıdır. | Yığın nedir? Yığın, tipik olarak düzgün bir şekilde düzenlenmiş bir nesne yığınıdır. Bilgi işlem mimarilerindeki yığınlar, verilerin son giren ilk çıkar şekilde eklendiği veya kaldırıldığı bellek bölgeleridir. Çok iş parçacıklı bir uygulamada, her iş parçacığının kendi yığını olacaktır. Yığın nedir? Yığın, gelişigüzel yığılmış şeylerin düzensiz bir koleksiyonudur. Bilgisayar mimarilerinde yığın, işletim sistemi veya bellek yöneticisi kitaplığı tarafından otomatik olarak yönetilen dinamik olarak ayrılmış bellek alanıdır. Yığın üzerindeki bellek, program yürütülürken düzenli olarak ayrılır, serbest bırakılır ve yeniden boyutlandırılır ve bu, parçalanma adı verilen bir soruna yol açabilir. Parçalanma, bellek nesneleri, aralarında ek bellek nesnelerini tutamayacak kadar küçük olan küçük boşluklarla ayrıldığında oluşur. Net sonuç, daha fazla bellek ayırmaları için kullanılamayan bir yığın alanı yüzdesidir. İkisi birlikte Çok iş parçacıklı bir uygulamada, her iş parçacığının kendi yığını olacaktır. Ancak, tüm farklı iş parçacıkları yığını paylaşacaktır. Farklı iş parçacıkları çok iş parçacıklı bir uygulamada öbeği paylaştığından, bu aynı zamanda iş parçacıkları arasında bir miktar koordinasyon olması gerektiği anlamına gelir, böylece yığın içindeki aynı bellek parçalarına erişmeye ve bunları değiştirmeye çalışmazlar Aynı zaman. Hangisi daha hızlı - yığın mı yoksa yığın mı? Ve neden? Yığın, yığından çok daha hızlıdır. Bunun nedeni, belleğin yığın üzerinde tahsis edilme biçimidir. Yığın üzerinde bellek ayırmak, yığın işaretçisini yukarı hareket ettirmek kadar basittir. Programlamaya yeni başlayanlar için, daha kolay olduğu için yığını kullanmak muhtemelen iyi bir fikirdir. Yığın küçük olduğu için, verileriniz için tam olarak ne kadar belleğe ihtiyaç duyacağınızı bildiğinizde veya verilerinizin boyutunun çok küçük olduğunu biliyorsanız kullanmak istersiniz. Verileriniz için çok fazla belleğe ihtiyacınız olduğunu bildiğinizde veya ne kadar belleğe ihtiyacınız olduğundan emin değilseniz (dinamik bir dizide olduğu gibi) yığını kullanmak daha iyidir. Java Bellek Modeli Yığın, yerel değişkenlerin (yöntem parametreleri dahil) depolandığı bellek alanıdır. Nesne değişkenleri söz konusu olduğunda, bunlar yalnızca öbek üzerindeki gerçek nesnelere yapılan referanslardır (işaretçiler). Bir nesne her oluşturulduğunda, o nesnenin verilerini (durumunu) tutmak için bir yığın bellek bir kenara ayrılır. Nesneler başka nesneler de içerebildiğinden, bu verilerin bir kısmı aslında bu iç içe geçmiş nesnelere referanslar içerebilir. | Sanırım birçok kişi bu konuda size çoğunlukla doğru cevaplar verdi. Ancak gözden kaçırılan bir ayrıntı, "yığın" ın aslında muhtemelen "ücretsiz mağaza" olarak adlandırılması gerektiğidir. Bu ayrımın nedeni, orijinal ücretsiz deponun "iki terimli yığın" olarak bilinen bir veri yapısıyla gerçekleştirilmiş olmasıdır. Bu nedenle, malloc () / free () 'nin erken uygulamalarından ayırma, bir yığından ayırmadır. Bununla birlikte, bu modern günde, çoğu ücretsiz mağaza, iki terimli yığınlar olmayan çok ayrıntılı veri yapılarıyla uygulanmaktadır. | Yığınla bazı ilginç şeyler yapabilirsiniz. Örneğin, alloca gibi işlevlere sahipsiniz (kullanımıyla ilgili çok sayıda uyarıları aşabileceğinizi varsayarak),bellek için özellikle yığını değil yığını kullanır. Bununla birlikte, yığın tabanlı bellek hataları, yaşadığım en kötü şeylerden bazıları. Yığın bellek kullanırsanız ve tahsis edilen bloğunuzun sınırlarını aşarsanız, bir segment hatasını tetikleme şansınız yüksektir. (% 100 değil: bloğunuz daha önce tahsis ettiğiniz başka bir blokla tesadüfen bitişik olabilir.) Ancak yığın üzerinde yaratılan değişkenler her zaman birbirine bitişik olduğundan, sınırların dışında yazmak başka bir değişkenin değerini değiştirebilir. Programımın mantık yasalarına uymayı bıraktığını hissettiğimde, bunun muhtemelen arabellek taşması olduğunu öğrendim. | Basitçe, yığın, yerel değişkenlerin oluşturulduğu yerdir. Ayrıca, bir alt rutini her çağırdığınızda, program sayacı (sonraki makine komutuna işaretçi) ve herhangi bir önemli yazmaç ve bazen parametreler yığına itilir. Ardından, alt yordamın içindeki herhangi bir yerel değişken yığına itilir (ve oradan kullanılır). Alt rutin bittiğinde, tüm bu şeyler yığından çıkar. PC ve kayıt verileri, çıktıkları gibi geri alır ve geri koyulur, böylece programınız neşeli bir şekilde devam edebilir. Yığın, bellek dinamik bellek ayırmalarının yapıldığı alandır (açık "yeni" veya "tahsis" çağrıları). Farklı boyutlardaki bellek bloklarını ve bunların tahsis durumlarını takip edebilen özel bir veri yapısıdır. "Klasik" sistemlerde RAM, yığın işaretçisi belleğin altından başlayacak, yığın işaretçisi yukarıdan başlayacak ve birbirlerine doğru büyüyecek şekilde yerleştirildi. Çakışırlarsa, RAM'iniz kalmıştır. Ancak bu, modern çok iş parçacıklı işletim sistemlerinde çalışmaz. Her iş parçacığının kendi yığını olması gerekir ve bunlar dinamik olarak oluşturulabilir. | WikiAnwser'dan. Yığın Bir işlev veya yöntem, sırayla başka bir işlevi vb. Çağıran başka bir işlevi çağırdığında, tüm bu işlevlerin yürütülmesi, en son işlevin değerini döndürene kadar askıda kalır. Bu askıya alınmış işlev çağrıları zinciri yığındır, çünkü yığındaki öğeler (işlev çağrıları) birbirine bağlıdır. Yığın, istisna işleme ve iş parçacığı yürütmelerinde dikkate alınması önemlidir. Yığın Yığın, programlar tarafından değişkenleri depolamak için kullanılan bellektir. Yığın öğesinin (değişkenler) birbirine bağımlılığı yoktur ve her zaman rastgele olarak herhangi bir zamanda erişilebilir. | Yığın Çok hızlı erişim Değişkenleri açıkça ayırmak zorunda değilsiniz Alan, CPU tarafından verimli bir şekilde yönetilir, bellek parçalanmaz Yalnızca yerel değişkenler Yığın boyutunda sınırlama (işletim sistemine bağlı) Değişkenler yeniden boyutlandırılamaz Yığın Değişkenlere küresel olarak erişilebilir Bellek boyutunda sınır yok (Nispeten) daha yavaş erişim Verimli alan kullanımı garanti edilmez, bellek blokları ayrıldıkça ve daha sonra serbest bırakıldıkça bellek zamanla parçalanabilir Belleği yönetmelisiniz (değişkenleri ayırmak ve serbest bırakmaktan siz sorumlusunuz) Değişkenler realloc () kullanılarak yeniden boyutlandırılabilir | Kısacası Her ikisi de bilgisayarın RAM'inde depolanan statik bellek ayırma için bir yığın ve dinamik bellek ayırma için bir yığın kullanılır. Detayda Yığın Yığın, CPU tarafından oldukça yakından yönetilen ve optimize edilen bir "LIFO" (son giren, ilk çıkar) veri yapısıdır. Bir işlev her yeni bir değişken bildirdiğinde, yığına "itilir". Daha sonra bir fonksiyondan her çıktığında, o fonksiyon tarafından yığına gönderilen tüm değişkenler serbest bırakılır (yani silinirler). Bir yığın değişkeni serbest bırakıldığında, bu bellek bölgesi diğer yığın değişkenleri için kullanılabilir hale gelir. Değişkenleri depolamak için yığını kullanmanın avantajı, belleğin sizin için yönetilmesidir. Belleği elle ayırmanız veya artık ihtiyacınız kalmadığında serbest bırakmanız gerekmez. Dahası, CPU yığın belleği çok verimli bir şekilde düzenlediğinden, yığın değişkenlerini okumak ve bunlara yazmak çok hızlıdır. Daha fazlası burada bulunabilir. Yığın Yığın, bilgisayarınızın belleğinin sizin için otomatik olarak yönetilmeyen ve CPU tarafından sıkı bir şekilde yönetilmeyen bir bölgesidir. Daha serbest yüzen bir bellek bölgesidir (ve daha büyüktür). Yığın üzerine bellek ayırmak için, yerleşik C işlevleri olan malloc () veya calloc () kullanmanız gerekir. Yığın üzerinde bellek ayırdıktan sonra, artık ihtiyacınız kalmadığında bu belleği serbest bırakmak için free () kullanmaktan sorumlusunuz. Bunu yapmazsanız, programınızda bellek sızıntısı olarak bilinen şey olacaktır. Yani, yığın üzerindeki bellek yine de bir kenara bırakılacaktır (ve diğer işlemler tarafından kullanılamayacaktır). Hata ayıklama bölümünde göreceğimiz gibi, bellek sızıntılarını tespit etmenize yardımcı olabilecek Valgrind adlı bir araç var. Yığının aksine, yığının değişken boyutta boyut kısıtlamaları yoktur (bilgisayarınızın bariz fiziksel sınırlamaları dışında). Yığın belleğinin okunması ve yazılması biraz daha yavaştır, çünkü öbek üzerindeki belleğe erişmek için işaretçiler kullanmak gerekir. Kısaca işaretçilerden bahsedeceğiz. Yığının aksine,öbek üzerinde oluşturulan değişkenlere programınızın herhangi bir yerinde herhangi bir işlev tarafından erişilebilir. Yığın değişkenleri esasen kapsam olarak küreseldir. Daha fazlası burada bulunabilir. Yığın üzerinde tahsis edilen değişkenler doğrudan belleğe kaydedilir ve bu belleğe erişim çok hızlıdır ve tahsis edilmesi, program derlendiğinde ele alınır. Bir işlev veya yöntem, sırayla başka bir işlevi vb. Çağıran başka bir işlevi çağırdığında, tüm bu işlevlerin yürütülmesi, en son işlevin değerini döndürene kadar askıda kalır. Yığın her zaman bir LIFO sırasına göre ayrılır, en son ayrılan blok her zaman serbest bırakılacak bir sonraki bloktur. Bu, yığının izini sürmeyi gerçekten kolaylaştırır, yığından bir bloğu serbest bırakmak, bir işaretçiyi ayarlamaktan başka bir şey değildir. Yığın üzerinde ayrılan değişkenlerin belleği çalışma zamanında tahsis edilir ve bu belleğe erişim biraz daha yavaştır, ancak yığın boyutu yalnızca sanal belleğin boyutuyla sınırlıdır. Yığının elemanlarının birbirine bağımlılığı yoktur ve her zaman rastgele erişilebilir. İstediğiniz zaman bir blok tahsis edebilir ve istediğiniz zaman serbest bırakabilirsiniz. Bu, herhangi bir zamanda yığının hangi bölümlerinin tahsis edildiğini veya ücretsiz olduğunu takip etmeyi çok daha karmaşık hale getirir. Yığını, derleme zamanından önce tam olarak ne kadar veri ayırmanız gerektiğini biliyorsanız ve çok büyük değilse kullanabilirsiniz. Yığını, çalışma zamanında tam olarak ne kadar veriye ihtiyacınız olacağını bilmiyorsanız veya çok fazla veri ayırmanız gerekiyorsa kullanabilirsiniz. Çok iş parçacıklı bir durumda, her iş parçacığı kendi tamamen bağımsız yığınına sahip olacak, ancak yığını paylaşacaklar. Yığın iş parçacığına özeldir ve yığın uygulamaya özeldir. Yığın, istisna işleme ve iş parçacığı yürütmelerinde dikkate alınması önemlidir. Her iş parçacığı bir yığın alır, ancak uygulama için tipik olarak yalnızca bir yığın vardır (ancak farklı ayırma türleri için birden çok yığın olması nadir değildir). Çalışma zamanında, uygulama daha fazla yığına ihtiyaç duyarsa, boş bellekten bellek ayırabilir ve yığın belleğe ihtiyaç duyarsa, uygulama için ayrılmış bellekten boş bellek ayırabilir. Hatta burada ve burada daha fazla ayrıntı verilmektedir. Şimdi sorunuzun yanıtlarına gelin. İşletim sistemi veya dil çalışma zamanı tarafından ne ölçüde kontrol ediliyorlar? İşletim sistemi, iş parçacığı oluşturulduğunda yığını her sistem düzeyindeki iş parçacığı için ayırır. Tipik olarak işletim sistemi, uygulama için yığın ayırmak üzere dil çalışma zamanı tarafından çağrılır. Daha fazlası burada bulunabilir. Kapsamları nedir? Zaten üstte verildi. "Derleme zamanından önce tam olarak ne kadar veri ayırmanız gerektiğini biliyorsanız ve çok büyük değilse yığını kullanabilirsiniz. Çalışma zamanında tam olarak ne kadar veriye ihtiyacınız olacağını bilmiyorsanız veya çok fazla veri ayırmanız gerekiyor. " Daha fazlasını burada bulabilirsiniz. Her birinin boyutunu ne belirler? Yığının boyutu, bir iş parçacığı oluşturulduğunda işletim sistemi tarafından belirlenir. Yığının boyutu uygulama başlangıcında belirlenir, ancak alan gerektiğinde büyüyebilir (ayırıcı işletim sisteminden daha fazla bellek ister). Birini daha hızlı yapan nedir? Yığın tahsisi çok daha hızlıdır çünkü tek yaptığı yığın işaretçisini hareket ettirmektir. Bellek havuzlarını kullanarak, yığın ayırmadan karşılaştırılabilir performans elde edebilirsiniz, ancak bu biraz ek karmaşıklık ve kendi baş ağrılarıyla birlikte gelir. Ayrıca, yığın ve yığın yalnızca bir performans değerlendirmesi değildir; aynı zamanda size nesnelerin beklenen ömrü hakkında çok şey söyler. Detaylar buradan bulunabilir. | Tamam, basitçe ve kısa bir deyişle, sipariş edilmiş ve sipariş edilmemiş anlamına geliyorlar ...! Yığın: Yığın öğelerde, işler üst üste gelir, bu da daha hızlı ve daha verimli işleneceği anlamına gelir! ... Yani her zaman belirli bir öğeyi işaret eden bir dizin vardır, ayrıca işlem daha hızlı olur, öğeler arasında da ilişki vardır! ... Öbek: Sipariş yok, işlem daha yavaş olacak ve değerler belirli bir sıra veya dizin olmadan birbirine karışacak ... Rastgele var ve aralarında bir ilişki yok ... bu nedenle yürütme ve kullanım süresi değişebilir ... Nasıl görünebileceklerini göstermek için aşağıdaki resmi de oluşturuyorum: | sanal bellekteki her işlemin yığını, yığın ve verileri: | 1980'lerde UNIX, büyük şirketler kendi başlarına yuvarlanan tavşanlar gibi yayıldı. Exxon'da bir tane vardı ve düzinelerce marka tarihe kaybetti. Hafızanın nasıl yerleştirildiği, birçok uygulayıcının takdirine kalmıştı. Tipik bir C programı hafızaya düz bir şekilde yerleştirildi brk () değerini değiştirerek artırma fırsatı. Tipik olarak, HEAP bu brk değerinin hemen altındaydı ve artan brk, kullanılabilir yığın miktarını artırdı. Tek Yığın, tipik olarak HEAP'in altında bir bellek alanıydı bir sonraki sabit bellek bloğunun tepesine kadar hiçbir değeri yoktur. Bu sonraki blok genellikle, yığın verileri tarafından üzerine yazılabilen CODE idi. döneminin ünlü hack'lerinden birinde. Tipik bir bellek bloğu BSS idi (sıfır blokdeğerler) bu, bir üreticinin teklifinde yanlışlıkla sıfırlanmadı. Bir diğeri, dizeler ve sayılar dahil olmak üzere başlatılmış değerleri içeren DATA idi. Üçüncüsü, CRT (C çalışma zamanı), ana, işlevler ve kitaplıkları içeren KOD idi. UNIX'te sanal belleğin ortaya çıkışı birçok kısıtlamayı değiştirir. Bu blokların bitişik olması için nesnel bir neden yoktur, veya boyut olarak sabitlenmiş veya şimdi belirli bir şekilde sipariş verilmiş. Elbette, UNIX'den önce bu kısıtlamalardan muzdarip olmayan Multics vardı. İşte o dönemin bellek düzenlerinden birini gösteren bir şematik. | Birkaç sent: Hafızayı grafiksel ve daha basit çizmenin iyi olacağını düşünüyorum: Oklar - yığının ve yığının büyümesinin nerede olduğunu, işlem yığını boyutunun işletim sisteminde tanımlanan sınırı olduğunu, iş parçacığındaki parametrelere göre iş parçacığı yığın boyutu sınırlarının genellikle API'yi oluşturduğunu gösterir. Yığın genellikle maksimum sanal bellek boyutuyla, örneğin 32 bit 2-4 GB için sınırlar. Çok basit yol: işlem yığını, işlem ve içindeki tüm iş parçacıkları için geneldir, malloc () gibi bir şeyle ortak durumda bellek ayırma için kullanılır. Yığın, genel durum işlevi dönüş işaretçileri ve değişkenlerinde saklamak için hızlı bir bellektir, işlev çağrısında parametreler, yerel işlev değişkenleri olarak işlenir. | Bazı cevaplar gıdıklandığından, akarıma katkıda bulunacağım. Şaşırtıcı bir şekilde, hiç kimse birden fazla (yani çalışan işletim sistemi düzeyinde iş parçacığı sayısıyla ilgili olmayan) çağrı yığınlarının yalnızca egzotik dillerde (PostScript) veya platformlarda (Intel Itanium) değil, aynı zamanda fiberlerde, yeşil iplerde de bulunduğundan bahsetmedi. ve coroutine'lerin bazı uygulamaları. Lifler, yeşil iplikler ve koroutinler birçok yönden benzerdir ve bu da kafa karışıklığına yol açar. Lifler ve yeşil iplikler arasındaki fark, birincisinin kooperatif çoklu görev kullanması, ikincisi ise kooperatif veya önleyici birini (veya hatta her ikisini) içerebilir. Lifler ve koroutinler arasındaki ayrım için buraya bakın. Her durumda, hem fiberlerin, hem yeşil ipliklerin hem de korutinlerin amacı, tek bir işletim sistemi düzeyinde iş parçacığı içinde aynı anda çalışan, ancak paralel olmayan (ayrım için bu SO sorusuna bakın) birden fazla işleve sahip olmak ve kontrolü birbirlerinden ileri geri aktarmaktır organize bir şekilde. Lifler, yeşil iplikler veya korutinler kullanırken, genellikle işlev başına ayrı bir yığına sahip olursunuz. (Teknik olarak, sadece bir yığın değil, işlev başına bütün bir yürütme bağlamıdır. En önemlisi, CPU kayıtları.) Her iş parçacığı için eşzamanlı olarak çalışan işlevler kadar yığın vardır ve iş parçacığı her işlevi yürütme arasında geçiş yapar programınızın mantığına göre. Bir fonksiyon sonuna kadar çalıştığında, yığını yok edilir. Dolayısıyla, yığınların sayısı ve yaşam süreleri dinamiktir ve işletim sistemi düzeyindeki iş parçacığı sayısına göre belirlenmez! "Genellikle işlev başına ayrı bir yığın var" dediğime dikkat edin. Hem yığınlanmış hem de yığınsız kurs uygulamaları vardır. En dikkate değer yığın içeren C ++ uygulamaları, Boost.Coroutine ve Microsoft PPL'nin async / await'tir. (Bununla birlikte, C ++ 17'ye önerilen C ++ 'nın devam ettirilebilir işlevleri (a.k.a. "zaman uyumsuz ve bekleme") büyük olasılıkla yığınsız eşgüdümler kullanır. C ++ standart kitaplığına fiber önerisi yakında geliyor. Ayrıca, bazı üçüncü taraf kitaplıkları var. Yeşil ipler Python ve Ruby gibi dillerde oldukça popülerdir. | Paylaşacak bir şeyim var, ancak ana noktalar zaten kapsanmış durumda. Yığın Çok hızlı erişim. RAM'de saklanır. Fonksiyon çağrıları, yerel değişkenler ve aktarılan fonksiyon parametreleri ile birlikte buraya yüklenir. Program kapsam dışına çıktığında alan otomatik olarak serbest bırakılır. Sıralı bellekte saklanır. Yığın Stack'e nispeten yavaş erişim. RAM'de saklanır. Dinamik olarak oluşturulan değişkenler burada saklanır ve bu daha sonra kullanımdan sonra ayrılmış belleğin serbest bırakılmasını gerektirir. Hafıza tahsisinin yapıldığı her yerde saklanır, her zaman işaretçi ile erişilir. İlginç not: İşlev çağrıları yığın halinde depolanmış olsaydı, 2 dağınık nokta ile sonuçlanırdı: Yığındaki sıralı depolama nedeniyle yürütme daha hızlıdır. Yığın içinde depolama, büyük zaman tüketimine neden olacak ve böylece tüm programın daha yavaş çalışmasına neden olacaktı. İşlevler yığın içinde saklanmış olsaydı (işaretçi tarafından gösterilen dağınık depolama), arayan adresine geri dönmenin bir yolu olmazdı (bu yığın, bellekteki sıralı depolama nedeniyle verir). | Vaov! Çok fazla cevap var ve bunlardan birinin doğru anladığını sanmıyorum ... 1) Neredeler ve nelerdir (fiziksel olarak gerçek bir bilgisayarın belleğinde)? Yığın, program görüntünüze tahsis edilen en yüksek bellek adresi olarak başlayan bellektir ve daha sonra oradan değeri düşer. Çağrılan işlev parametreleri ve işlevlerde kullanılan tüm geçici değişkenler için ayrılmıştır. İki yığın vardır: genel ve özel. Özel yığın, programınızdaki son kod baytından sonra 16 baytlık bir sınırda (64 bit programlar için) veya 8 baytlık bir sınırda (32 bit programlar için) başlar ve daha sonraoradan değer. Varsayılan yığın olarak da adlandırılır. Özel yığın çok büyük olursa, yığın çok büyük olursa yığın yığınla üst üste geleceği gibi, yığın alanıyla çakışacaktır. Yığın daha yüksek bir adreste başladığından ve daha düşük bir adrese doğru ilerlediğinden, uygun hackleme ile yığını o kadar büyük yapabilirsiniz ki, özel yığın alanını aşar ve kod alanıyla örtüşür. İşin püf noktası, koda bağlayabileceğiniz kadar kod alanıyla örtüşmektir. Yapması biraz zor ve bir programın çökmesini riske atarsınız, ancak kolay ve çok etkilidir. Genel yığın, program görüntü alanınızın dışında kendi bellek alanında bulunur. Bellek kaynakları azalırsa, sabit diske sifonlanacak olan bu bellektir. 2) İşletim sistemi veya dil çalışma zamanı tarafından ne ölçüde kontrol ediliyorlar? Yığın, programcı tarafından kontrol edilir, özel yığın işletim sistemi tarafından yönetilir ve genel yığın, bir işletim sistemi hizmeti olduğu için kimse tarafından kontrol edilmez - siz isteklerde bulunursunuz ve bunlar verilir veya reddedilir. 2b) Kapsamı nedir? Hepsi program için küreseldir, ancak içerikleri özel, genel veya küresel olabilir. 2c) Her birinin boyutunu ne belirler? Yığının ve özel yığının boyutu, derleyici çalışma zamanı seçenekleriniz tarafından belirlenir. Genel yığın, bir boyut parametresi kullanılarak çalışma zamanında başlatılır. 2d) Birini daha hızlı yapan nedir? Hızlı olacak şekilde tasarlanmamıştır, kullanışlı olacak şekilde tasarlanmıştır. Programcının bunları nasıl kullandığı, "hızlı" mı yoksa "yavaş" mı olduklarını belirler REF: https://norasandler.com/2019/02/18/Write-a-Compiler-10.html https://docs.microsoft.com/en-us/windows/desktop/api/heapapi/nf-heapapi-getprocessheap https://docs.microsoft.com/en-us/windows/desktop/api/heapapi/nf-heapapi-heapcreate | Pek çok cevap kavram olarak doğrudur, ancak alt yordamları çağırmaya izin vermek için donanım (yani mikroişlemci) tarafından bir yığına ihtiyaç duyulduğuna dikkat etmeliyiz (assembly dilinde CALL ..). (OOP adamları buna yöntemler diyecek) Yığın üzerinde dönüş adreslerini kaydedersiniz ve arama → push / ret → pop doğrudan donanımda yönetilir. Yığını parametreleri geçmek için kullanabilirsiniz .. yazmaçları kullanmaktan daha yavaş olsa bile (bir mikroişlemci ustası derdi veya 1980'lerin BIOS kitabı ...) Yığın olmadan hiçbir mikroişlemci çalışamaz. (alt yordamlar / işlevler olmadan assembly dilinde bile bir program hayal edemiyoruz) Yığın olmadan yapabilir. (Bir montaj dili programı, yığın bir işletim sistemi konsepti olduğundan, malloc olarak, yani bir OS / Lib çağrısı olmadan çalışabilir. Yığın kullanımı şu şekilde daha hızlıdır: Donanım mı ve hatta push / pop çok verimli. malloc, çekirdek moduna girmeyi, bazı kodları yürütmek için kilit / semafor (veya diğer senkronizasyon ilkelleri) kullanmayı ve tahsisi izlemek için gereken bazı yapıları yönetmeyi gerektirir. | Yığın, işletim sistemi veya bellek yöneticisi kitaplığı tarafından otomatik olarak yönetilen dinamik olarak ayrılmış bellek alanıdır. İstediğiniz zaman bir blok tahsis edebilir ve istediğiniz zaman serbest bırakabilirsiniz. Yığın tahsisi, hangi belleğin ayrıldığına ve neyin ayrılmadığına ilişkin tam bir kayıt tutmanın yanı sıra parçalanmayı azaltmak için bazı ek bakımlar, istenen boyuta uyacak kadar büyük bitişik bellek bölümleri bulma vb. Bellek, boş alan bırakılarak herhangi bir zamanda serbest bırakılabilir. Yığın büyüdükçe yeni bloklar genellikle daha düşük adreslerden daha yüksek adreslere tahsis edilir. Böylece, yığını, bellek ayrıldığında boyutu büyüyen bir bellek blokları yığını olarak düşünebilirsiniz. Yığın bir ayırma için çok küçükse, boyut genellikle temeldeki işletim sisteminden daha fazla bellek alınarak artırılabilir. Yığından ayrılan bellek, aşağıdakilerden biri gerçekleşene kadar ayrılmış olarak kalacaktır: Hafıza serbest bırakıldı Program sona eriyor Yığın: Tıpkı yığın gibi bilgisayar RAM'inde saklanır. Yığın üzerinde oluşturulan değişkenler kapsam dışına çıkar ve otomatik olarak serbest bırakılır. Yığın üzerindeki değişkenlere kıyasla ayırmak çok daha hızlı. Parametre geçişi için kullanılan yerel verileri, dönüş adreslerini depolar. Çok fazla yığın kullanıldığında yığın taşmasına neden olabilir (çoğunlukla sonsuz veya çok derin özyinelemeden, çok büyük tahsislerden). Tam olarak ne kadar veriye ihtiyacınız olduğunu biliyorsanız yığını kullanırsınız. derleme zamanından önce ayırın ve çok büyük değil. Genellikle programınız önceden belirlenmiş bir maksimum boyuta sahiptir. başlar. Yığın: Tıpkı yığın gibi bilgisayar RAM'inde saklanır. C ++ 'da, öbek üzerindeki değişkenler elle yok edilmeli ve asla kapsam dışında kalmak. Veriler silme, silme [] veya ücretsiz olarak serbest bırakılır. Yığın üzerindeki değişkenlere kıyasla ayırmak daha yavaştır. Program tarafından kullanılmak üzere bir veri bloğu tahsis etmek için isteğe bağlı olarak kullanılır. Çok fazla tahsis olduğunda parçalanabilir ve serbest bırakmalar. C ++ veya C'de, yığın üzerinde oluşturulan veriler işaretçilerle gösterilecektir. ve sırasıyla new veya malloc ile tahsis edilmiştir. Çok büyük bir arabellek istenirse ayırma hataları olabilir. tahsis edilecek. Sentam olarak ne kadar veriye sahip olduğunuzu bilmiyorsanız yığını kullanırdı çalışma zamanında veya çok fazla veri ayırmanız gerektiğinde ihtiyacınız olacaktır. Hafıza sızıntılarından sorumlu. | Yığın, esasen, öğelerini basitçe yöneten, erişimi kolay bir bellektir. bir - iyi - yığın olarak. Yalnızca boyutu önceden bilinen öğeler yığına girebilir. Sayılar, dizeler ve booleler için durum budur. Yığın, önceden belirleyemediğiniz öğeler için bir hafızadır. tam boyut ve yapı. Nesneler ve diziler değiştirilebildiğinden ve çalışma zamanında değişiklik, yığına girmeleri gerekir. Kaynak: Academind | CPU yığını ve yığını, fiziksel olarak CPU ve yazmaçların bellekle nasıl çalıştığı, makine birleştirme dilinin nasıl çalıştığı ile ilgilidir, bu diller küçük şeylere karar verse bile üst düzey dillerin kendileri ile değil. Tüm modern CPU'lar "aynı" mikroişlemci teorisi ile çalışır: hepsi "kayıtlar" denen şeye dayanır ve bazıları performans kazanmak için "yığın" içindir. Baştan beri tüm CPU'ların yığın yazmaçları var ve bildiğim gibi her zaman buradaydılar. Bir OO sanal makine birleştirme diline sahip olmak için paradigmayı değiştiren Microsoft'a ve Ara Diline (IL) kadar olan varyasyonlara rağmen, montaj dilleri başından beri aynıdır. Böylece gelecekte bir miktar CLI / CIL CPU'ya sahip olabileceğiz (bir MS projesi). CPU'ların bellek erişimini hızlandırmak için yığın yazmaçları vardır, ancak işlemcinin tüm kullanılabilir belleğine tam erişim sağlamak için diğer yazmaçların kullanımına kıyasla sınırlıdırlar. Bu yüzden yığın ve yığın ayırmalarından bahsettik. Özet olarak ve genel olarak, yığın çok büyük ve yavaştır ve yığın küçük ve hızlı olduğundan ve "yerel" değişkenler ve referanslar için (bunları yönetmeyi unutacak gizli işaretçiler) "genel" örnekler ve nesne içeriği içindir. Dolayısıyla, new anahtar kelimesini bir yöntemde kullandığımızda, referans (bir int) yığında oluşturulur, ancak hatırlıyorsam, nesne ve tüm içeriği (değer türleri ve nesneler) yığın içinde oluşturulur. Ancak yığın içinde yerel temel değer türleri ve diziler oluşturulur. Bellek erişimindeki fark, referanslama düzeyindeki hücrelerdedir: işlemin genel belleği olan yığını adreslemek, adresleme açısından yerel olarak "daha fazla" olan yığından daha karmaşıklık gerektirir, çünkü CPU yığını hatırlıyorsam register temel adres olarak kullanılıyor. Bu nedenle, çok uzun veya sonsuz tekrarlı çağrılarımız veya döngülerimiz olduğunda, sistemi modern bilgisayarlarda dondurmadan hızlı bir şekilde yığın taşması yaşıyoruz ... .NET'te C # Yığın (ing) Vs Stack (ing) Yığın ve Yığın: Farkı Bilin C # depolandığı yerde statik sınıf bellek tahsisi Yığın ve yığın ne ve nerede? https://en.wikipedia.org/wiki/Memory_management https://en.wikipedia.org/wiki/Stack_register Assembly dili kaynakları: Assembly Programlama Eğitimi Intel® 64 ve IA-32 Mimarileri Yazılım Geliştirici Kılavuzları | Gerçekten güzel bir tartışma için teşekkür ederim ama gerçek bir çaylak olarak talimatların nerede tutulduğunu merak ediyorum? BAŞLANGIÇ'ta bilim adamları iki mimari arasında karar veriyorlardı (her şeyin DATA olarak kabul edildiği von NEUMANN ve bir hafıza alanının talimatlar ve diğerinin veriler için ayrıldığı HARVARD). Nihayetinde von Neumann tasarımına gittik ve şimdi her şey "aynı" olarak kabul ediliyor. Bu, montajı öğrenirken işimi zorlaştırdı https://www.cs.virginia.edu/~evans/cs216/guides/x86.html çünkü yazmaçlar ve yığın işaretçileri hakkında konuşuyorlar. Yukarıdaki her şey DATA hakkında konuşuyor. Tahminim, bir talimat belirli bir bellek ayak izine sahip tanımlanmış bir şey olduğu için, yığına gidecektir ve bu nedenle, derlemede tartışılan tüm 'bu' yazmaçlar yığın üzerindedir. Elbette sonra dinamik bir yapıya gelen komutlar ve verilerle nesne yönelimli programlama geldi, bu yüzden şimdi komutlar da yığın üzerinde saklanacak mı? | Oldukça aktif soru. Bu soruyu cevaplamak için 10 itibar kazanın. İtibar koşulu, bu sorunun istenmeyen postalardan ve yanıtlanmayan etkinliklerden korunmasına yardımcı olur. Aradığın cevap değil mi? Bellek yönetimi yığını etiketli diğer sorulara göz atın, dilden bağımsız yığın dinamik bellek ayırma veya kendi sorunuzu sorun.